home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-06-22 | 19.5 KB | 747 lines | [TEXT/MPS ] |
- #include "ArrangeCallbacks.h"
- #include "PluginLibrary.h"
-
- #include <Dialogs.h>
- #include <OSA.h>
- #include <Resources.h>
- #include <AERegistry.h>
-
- #if defined (__MWERKS__) && defined (PLUGIN_GLOBALS)
- #include "A4Stuff.h"
- #endif
-
-
- /* This file defines a "generic" plugin module for Arrange 2.0. To
- * use it, you should modify the Plugin class definition by adding
- * new fields and private functions, and make corresponding changes in the
- * "Plugin" section at the bottom of the file. You should not have to
- * look at or make any changes to the "Main entry point" section in the middle
- * of the file. This section contains code to create an instance of
- * Plugin when the module is loaded, and forward hook calls from Arrange to
- * the appropriate Plugin functions.
- *
- * There is an associated Rez file, GenericPlugin.r, which defines the
- * 'MDdf' resource needed for each Arrange plugin module. To create a plugin
- * module, compile GenericPlugin.r to produce an 'MDdf' resource, and
- * compile and link this file to produce an 'MDcd' resource with the same ID.
- *
- * This version of GenericPlugin.cp was written by Steve Newman on 12/24/93.
- * Last updated 7/15/94.
- */
-
-
- #define ModuleRsrcID -0x8000
-
- #define OurModuleID 0x70000000 // Unique module ID; replace with a value
- // obtained from CE Software.
- #define baseCmdCode OurModuleID
-
- #define pluginName "Stock Quote Plugin" // controls our name in the About menu
- #define pluginAboutMenuText "About Stock Quote Plugin"
-
- #define aboutCmdCode (baseCmdCode + 0)
- #define updateQuoteCmdCode (baseCmdCode + 1)
-
-
- #if defined (__MWERKS__) && defined (PLUGIN_GLOBALS)
- #define SetupA4 long lOldA4 = SetCurrentA4 ();
- #define TearDownA4 SetA4 (lOldA4);
- #define UnloadSegs UnloadSegsFunc ();
-
- static void UnloadSegsFunc ();
- #else
- #define SetupA4
- #define TearDownA4
- #define UnloadSegs
- #endif //__MWERKS__
-
-
- typedef struct {
- Str255 cURLAddress;
- Str255 cComment;
- Str255 cTitle;
- arDocumentPtr whichDoc;
- const ArrangeCallbackTbl* calls;
- arNoteID cTheTourNote;
- short whichNote;
- } myprefs;
-
- typedef struct {
- arFieldID lTitleField;
- arFieldID lValueField;
- arFieldID lIndexField;
- arFieldID lChangeField;
-
- } sIDList;
-
- class Plugin
- {
- public:
- Plugin(const ArrangeCallbackTbl* theCalls);
- ~Plugin();
-
- arHookResult ClickNotify( arClickLocation loc, Point where, Short modifiers,
- Short clickCount, arNoteID note, arFieldID field,
- arPathID path );
- arHookResult KeyNotify ( Short theChar, Short key, Short modifiers );
- arHookResult MenuNotify ( Integer commandCode, Integer commandParam,
- Short modifiers );
- arHookResult FieldNotify( arNoteID note, arFieldID field, arFieldAction action,
- const char* choiceText );
- void TopicNotify( arTopicID newTopic, arWindowID newWindow,
- arTopicAction action );
- void TickNotify ( );
- arHookResult FileNotify ( arFileAction action );
- arHookResult QuitNotify ( );
- void ATMNotify ( );
-
- private:
- const ArrangeCallbackTbl* calls; // callback table
- short mQuotes;
- myprefs theprefs;
- ComponentInstance scriptingComponent;
-
- void UpdateTheQuotes ();
- void UpdateNote(arNoteID);
- OSErr InitComponent();
- OSErr GetQuote(ConstStr255Param, StringPtr, StringPtr, StringPtr);
- void SetChange(arNoteID selNote, short index, StringPtr newValue);
- }; // Plugin
-
-
- /*************************************************************************/
- /**************************** Main entry point ***************************/
- /*************************************************************************/
-
- /* Root entry point for the module - must be the first function in the
- * file, so that the linker will place it first in the code segment.
- * This is the routine which Arrange calls at application startup time
- * (and again at quit time).
- *
- * Most plug-ins will not need to modify this routine or the Hook functions
- * immediately following. All customization can be done in the "Plugin"
- * section (below).
- */
- extern "C" Integer main( ModuleParamBlock *pb, pModuleRootAction action,
- Integer /*p1*/ ENDP )
- {
- SetupA4;
-
- Integer lResult = 0;
-
- /* Extract the callback table from our parameter block, and coerce it
- * to the extended Arrange table.
- */
- ArrangeCallbackTbl* calls = (ArrangeCallbackTbl*)(pb->calls);
-
- Assert (sizeof (Byte) == 1);
- Assert (sizeof (Short) == 2);
- Assert (sizeof (Integer) == 4);
- Assert (sizeof (Float) == 8);
-
- switch (action)
- {
- case mrLoad:
- {
- // Allocate memory and create a new Plugin object.
- void* storage = calls->mem->AllocMem( sizeof(Plugin),
- amFreeStore | amErrIfNoMem );
- pb->moduleRefcon = uInteger(new(storage) Plugin(calls));
- lResult = 1;
- }
- break;
-
- case mrUnload:
- {
- /* Dispose of the Plugin object and release the memory
- * it occupies.
- */
- delete (Plugin*)(pb->moduleRefcon);
- calls->mem->DeallocMem((void*)(pb->moduleRefcon), amFreeStore);
- lResult = 0;
- }
- break;
-
- case mrFindEntry:
- default:
- {
- /* This module contains no extended entry points, so we always
- * return 0 for the mrFindEntry message. Most plug-ins will not
- * use extended entry points.
- */
- lResult = 0;
- }
- break;
-
- } // switch (action)
-
- UnloadSegs;
- TearDownA4;
- return lResult;
- } // main
-
- #if defined (__MWERKS__) && defined (PLUGIN_GLOBALS)
- #pragma segment PluginLib
- static void PluginLibSeg (void)
- {
- }
-
- #pragma segment Main
- static void UnloadSegsFunc ()
- {
- // Put segment unloading code here.
- // Do NOT use UnloadSeg!
- UnloadA4Seg (PluginLibSeg);
- }
- #endif //__MWERKS__ && PLUGIN_GLOBALS
-
- /* These hook functions simply pass control to the appropriate function
- * in the Plugin object.
- */
- static arHookResult OurClickHook( ModuleParamBlock* pb, arClickLocation loc,
- Point where, pShort modifiers, pShort clickCount,
- arNoteID note, arFieldID field,
- arPathID path ENDP )
- {
- SetupA4;
- arHookResult eResult = ((Plugin*)(pb->moduleRefcon))->ClickNotify( loc, where, modifiers,
- clickCount, note, field,
- path );
- UnloadSegs;
- TearDownA4;
- return eResult;
- }
-
-
- static arHookResult OurKeyHook( ModuleParamBlock* pb, pShort theChar, pShort key,
- pShort modifiers ENDP )
- {
- SetupA4;
- arHookResult eResult = ((Plugin*)(pb->moduleRefcon))->KeyNotify(theChar, key, modifiers);
- UnloadSegs;
- TearDownA4;
- return eResult;
- }
-
-
- static arHookResult OurMenuHook( ModuleParamBlock* pb, Integer commandCode,
- Integer commandParam, pShort modifiers ENDP )
- {
- SetupA4;
- arHookResult eResult = ((Plugin*)(pb->moduleRefcon))->MenuNotify( commandCode, commandParam,
- modifiers );
- UnloadSegs;
- TearDownA4;
- return eResult;
- }
-
-
- static arHookResult OurFieldHook( ModuleParamBlock* pb, arNoteID note,
- arFieldID field, arFieldAction action,
- const char* choiceText ENDP )
- {
- SetupA4;
- arHookResult eResult = ((Plugin*)(pb->moduleRefcon))->FieldNotify( note, field, action,
- choiceText );
- UnloadSegs;
- TearDownA4;
- return eResult;
- }
-
-
- static void OurTopicHook( ModuleParamBlock* pb, arTopicID newTopic,
- arWindowID newWindow, arTopicAction action ENDP )
- {
- SetupA4;
- ((Plugin*)(pb->moduleRefcon))->TopicNotify(newTopic, newWindow, action);
- UnloadSegs;
- TearDownA4;
- }
-
-
- static void OurTickHook(ModuleParamBlock* pb ENDP)
- {
- SetupA4;
- ((Plugin*)(pb->moduleRefcon))->TickNotify();
- UnloadSegs;
- TearDownA4;
- }
-
-
- static arHookResult OurFileHook(ModuleParamBlock* pb, arFileAction action ENDP)
- {
- SetupA4;
- arHookResult eResult = ((Plugin*)(pb->moduleRefcon))->FileNotify(action);
- UnloadSegs;
- TearDownA4;
- return eResult;
- }
-
-
- static arHookResult OurQuitHook(ModuleParamBlock* pb ENDP)
- {
- SetupA4;
- arHookResult eResult = ((Plugin*)(pb->moduleRefcon))->QuitNotify();
- UnloadSegs;
- TearDownA4;
- return eResult;
- }
-
-
- static void OurATMHook(ModuleParamBlock* pb ENDP)
- {
- SetupA4;
- ((Plugin*)(pb->moduleRefcon))->ATMNotify();
- UnloadSegs;
- TearDownA4;
- }
-
-
- /*************************************************************************/
- /********************************* Plugin ********************************/
- /*************************************************************************/
-
- /* Construct a Plugin object. This is called once, from the OurModuleRoot
- * function, when the module is initialized (i.e. at application startup time).
- */
- Plugin::Plugin(const ArrangeCallbackTbl* theCalls)
- {
- // Record the callback table for future use.
- calls = theCalls;
-
- /* These commands, if un-commented-out, register this plugin to be called
- * by Arrange when various events occur. For example, if you un-comment-out
- * the call to SetClickHook, then Plugin::ClickNotify will be called
- * whenever the user clicks in any of the locations described in the
- * arClickLocation enum.
- */
- // calls->ui->SetClickHook(OurClickHook, 0, true);
- // calls->ui->SetKeyHook (OurKeyHook, 0, true, charFilter, keyFilter, modFilter);
- // calls->ui->SetMenuHook (OurMenuHook, 0, true, whichCommand);
- // calls->ui->SetFieldHook(OurFieldHook, 0, true, whichField);
- // calls->ui->SetTopicHook(OurTopicHook, 0, true);
- // calls->ui->SetTickHook (OurTickHook, 0, true);
- // calls->ui->SetFileHook (OurFileHook, 0, true);
- // calls->ui->SetQuitHook (OurQuitHook, 0, true);
- // calls->ui->SetATMHook (OurATMHook, 0, true);
-
-
- // Add an item to the About Plugins menu for this plugin.
- calls->ui->AddMenuItem(mPluginAbout, pluginAboutMenuText, 0, aboutCmdCode, 0);
- calls->ui->AddMenuItem(mTools, "Update Quote", 0, updateQuoteCmdCode,2);
-
- calls->ui->SetMenuHook(OurMenuHook, 1, true, aboutCmdCode);
- calls->ui->SetMenuHook(OurMenuHook, 2, true, updateQuoteCmdCode);
-
- InitComponent();
- } // Plugin constructor
-
-
- /* Dispose of a Plugin object. This is called when Arrange terminates. You
- * should free up any data structures which you allocation in the Plugin
- * constructor (above).
- */
- Plugin::~Plugin()
- {
- } // ~Plugin
-
-
- /* This function is called whenever the user clicks in an "interesting place"
- * in a document window. It should return true if we handle the click, false
- * (the normal case) when the click should be passed along to other plug-ins
- * or to Arrange's normal event processing. See the documentation for
- * SetClickHook for more details.
- */
- arHookResult Plugin::ClickNotify( arClickLocation loc, Point where,
- Short modifiers, Short clickCount,
- arNoteID note, arFieldID field,
- arPathID path )
- {
- return false; // Let Arrange handle the event
- } // ClickNotify
-
-
- /* This function is called whenever the user types a key which matches the
- * filters we pass to SetKeyHook in Plugin's constructor. It should return
- * true if we handle the event, false (the normal case) when the event
- * should be passed along to other plug-ins or to Arrange's normal event
- * processing. See the documentation for SetKeyHook for more details.
- */
- arHookResult Plugin::KeyNotify(Short theChar, Short key, Short modifiers)
- {
- return false; // Let Arrange handle the event
- } // KeyNotify
-
-
- /* This function is called whenever the user chooses a menu item for which
- * we have registered (via the SetMenuHook function). It should return true
- * if we handle the command, false (the normal case) when the command should
- * be passed along to other plug-ins or to Arrange's normal event processing.
- * See the documentation for SetMenuHook for more details.
- */
- arHookResult Plugin::MenuNotify( Integer commandCode, Integer commandParam,
- Short modifiers )
- {
- /* If this is our About menu item, display our about-box dialog and return
- * true to indicate we handled the command.
- */
- if (commandCode == aboutCmdCode)
- {
- Alert(ModuleRsrcID, nil);
- return true;
- }
- else if (commandCode == updateQuoteCmdCode)
- {
- UpdateTheQuotes();
- return true;
- }
- else
- return false; // Let Arrange handle the event
-
- } // MenuNotify
-
-
- /* If we register to recieve events for a field by calling SetFieldHook, this
- * function will be called for any events in that field. It should return
- * false in almost all cases. See the documentation for SetFieldHook for
- * more details.
- */
- arHookResult Plugin::FieldNotify( arNoteID note, arFieldID field,
- arFieldAction action, const char* choiceText )
- {
- return false;
- } // FieldNotify
-
-
- /* This function is called whenever the user switches windows or changes
- * the current folder/topic/view in the front window. See the documentation
- * for SetTopicHook for more details.
- */
- void Plugin::TopicNotify( arTopicID newTopic, arWindowID newWindow,
- arTopicAction action )
- {
- } // TopicNotify
-
-
- /* This function is called periodically, whenever Arrange recieves a null
- * event from the Event Manager.
- */
- void Plugin::TickNotify()
- {
-
- } // TickNotify
-
-
- /* This function is called whenever various file-level events occur. It
- * should return true in almost all cases. See the documentation for
- * SetFileHook for more details.
- */
- arHookResult Plugin::FileNotify(arFileAction action)
- {
- return true;
- } // FileNotify
-
-
- /* This function is called if the user voluntarily quits Arrange. It should
- * return true to allow the user to quit, false to prevent it. See the
- * documentation for SetQuitHook for more details.
- */
- arHookResult Plugin::QuitNotify()
- {
- return true;
- } // QuitNotify
-
-
- /* This function is called whenever the user clicks in the menu bar or types
- * a command key, just before processing the event. It should do any fixing
- * up of menus which might be necessary based on the current state of affairs.
- * See the documentation for SetATMHook for more details.
- */
- void Plugin::ATMNotify()
- {
- } // ATMNotify
-
-
- /*Boolean Plugin::GetMyIDs(sIDList *theIDs)
- {
- char topic[13] = "Stock Quotes";
-
- char title[6] = "Title";
- char index[6] = "Index";
- char value[6] = "Value";
- char change[7] = "Change";
-
- theIDs->lTitleField = calls->sysObj->LookupObjectName ( arTopic,(char*) (&topic), true);
- if(!theIDs->lTitleField)
- return false;
-
- theIDs->lTopicContentsFieldID = calls->sysObj->GetBuiltInObject (boTopicContentsField);
- if (!theIDs->lTopicContentsFieldID)
- {
- return false;
- }
-
- theIDs->lTitleField = calls->sysObj->LookupObjectName ( arField,(char*) (&title), true);
- if(!theIDs->lTitleField)
- return false;
-
- theIDs->lIndexField = calls->sysObj->LookupObjectName ( arField,(char*) (&index), true);
- if(!theIDs->lTitleField)
- return false;
-
- theIDs->lValueField = calls->sysObj->LookupObjectName ( arField,(char*) (&value), true);
- if(!theIDs->lTitleField)
- return false;
-
- theIDs->lChangeField = calls->sysObj->LookupObjectName ( arField,(char*) (&change), true);
- if(!theIDs->lTitleField)
- return false;
-
-
- return true;
- }
- */
-
- void Plugin::UpdateTheQuotes ( )
- {
- Integer i;
- short whichnote;
- // Determine whether there is a selection and how many notes it contains.
- Integer selCount;
-
- arNoteID selNote;
- arNoteID parentNote;
- arFieldID selField;
- Integer selStart;
- Integer selEnd;
-
- short thecount;
- arFieldID theField;
- arNoteInfo thetopicinfo;
- short thelength;
- Str255 tempstr;
- Ptr theptr;
- char TheName[32]="Reformatting";
- Boolean firstchange = true;
-
- Str31 promptstr = "\pRetrieving the quote...";
-
-
- if (!calls->sel->FlushSelection(false))
- {
- return;
- }
-
- switch (calls->sel->GetSelection(&selNote, &selField, &selStart, &selEnd))
- {
- case stNote:
- case stFieldContents:
- case stMultipleNotes:
- case stMultipleFields:
- case stField:
- case stText: // selected text is treated specially
- default:
- calls->dlg->DisplayNotify( (const char*)&promptstr[1], nfShowImmediately);
- UpdateNote(selNote);
- calls->dlg->ClearNotify();
- return;
-
- } // switch (GetSelection result)
-
- return;
- }
-
-
- void Plugin::UpdateNote(arNoteID selNote)
- {
- arFieldID theField = calls->notes->GetNoteField(selNote, 1);
- if(!theField)
- DebugStr("\pno field");
-
- if (theField!=nil)
- {
-
- arFieldInfo info;
- info.versNum = 1;
- calls->sysObj->GetFieldInfo(theField, &info);
-
- if(info.type!=arFTText)
- DebugStr("\pnot a text");
-
- if (info.type==arFTText)
- {
- Str255 index;
-
- index[0] = calls->data->GetFieldTextLen(selNote, theField);
- if (index[0])
- {
- Str255 price = "\p", change = "\p", name = "\p";
- index[0] = calls->data->GetFieldText(selNote, theField, index[0]+1, (char*)(index + 1));
- OSErr err = GetQuote(index, price, name, change);
- if(!err)
- {
- SetChange(selNote, 0, name);
- SetChange(selNote, 2, price);
- SetChange(selNote, 3, change);
-
- calls->sel->FlushSelection(false);
- }
- }
- }
- }
- }
-
- void Plugin::SetChange(arNoteID selNote,
- short index,
- StringPtr newValue)
- {
- arFieldID theField = calls->notes->GetNoteField(selNote, index);
- if(theField)
- calls->data->SetFieldText( selNote,
- theField,
- (char *)(newValue + 1),
- newValue[0],
- 0);
- }
-
- OSErr Plugin::GetQuote(ConstStr255Param index,
- StringPtr price, StringPtr name, StringPtr change)
- {
- AEDesc target = {typeNull, nil};
-
- AppleEvent theEvent;
- OSErr err = AECreateAppleEvent( 'core',
- 'clos',
- &target,
- kAutoGenerateReturnID,
- 0,
- &theEvent);
-
- err = AEPutParamPtr( &theEvent,
- keyDirectObject,
- typeChar,
- index + 1,
- index[0]);
-
- AEDesc scriptData = {typeNull, 0};
-
- scriptData.dataHandle = GetResource('scpt', 128);
- scriptData.descriptorType = 'scpt';
- if(scriptData.dataHandle == 0)
- DebugStr("\pNo data");
-
- OSAID scriptID;
- err = OSALoad( scriptingComponent,
- &scriptData,
- kOSAModePreventGetSource,
- &scriptID);
-
- if(err)
- DebugStr("\pcould not load script");
-
- if(!err)
- {
- AppleEvent reply = { typeNull, 0};
- OSAID result;
- err = OSAExecuteEvent( scriptingComponent,
- &theEvent,
- scriptID,
- kOSAModeNull,
- &result);
-
- if(err)
- DebugStr("\pcould not execute event");
-
- AEDescList resultList = { typeNull, 0};
-
- if(!err)
- {
- /*err = AEGetParamDesc(&reply,
- keyAEResult,
- typeAEList,
- &resultList);*/
-
- err = OSACoerceToDesc( scriptingComponent,
- result,
- typeAEList,
- kOSAModeNull,
- &resultList);
- long size;
- AEKeyword key;
- DescType type;
- if(!err)
- {
- err = AEGetNthPtr( &resultList,
- 1,
- typeChar,
- &key,
- &type,
- name + 1,
- 255,
- &size);
- name[0] = size;
-
- err = AEGetNthPtr( &resultList,
- 2,
- typeChar,
- &key,
- &type,
- price + 1,
- 255,
- &size);
- price[0] = size;
-
- err = AEGetNthPtr( &resultList,
- 3,
- typeChar,
- &key,
- &type,
- change + 1,
- 255,
- &size);
- change[0] = size;
- }
- }
-
- }
- return err;
- }
-
- OSErr Plugin::InitComponent()
- {
- OSAError err = 0;
- ComponentDescription descr;
- Component aComponent;
- ComponentInstance aScriptingComponent;
-
-
- descr.componentType = kOSAComponentType;
- descr.componentSubType = (OSType) 0;
- descr.componentManufacturer = (OSType) 0;
- descr.componentFlags = kOSASupportsCompiling +
- kOSASupportsGetSource +
- kOSASupportsConvenience +
- kOSASupportsEventHandling;
- descr.componentFlagsMask = descr.componentFlags;
-
- aComponent = FindNextComponent(nil, &descr);
-
- if (!aComponent)
- err = paramErr;
- else
- {
- aScriptingComponent = OpenComponent(aComponent);
-
- if (!aScriptingComponent)
- err = paramErr;
- else if (aScriptingComponent)
- err = OSASetActiveProc(aScriptingComponent, 0, 0);
- }
-
- scriptingComponent = aScriptingComponent;
-
- if(err)
- DebugStr("\pCould not init component");
- return err;
- }
-